import math
import random
import cPickle as pickle
from neat import config, population, chromosome, genome, visualize
from neat.nn import nn_pure as nn
#from neat.nn import nn_cpp as nn # C++ extension

# Domination game imports
from domination import core, run
import shutil
from tempfile import mkstemp
from shutil import move
from os import remove, close

def replace(file, pattern, subst):
    #Create temp file
    fh, abs_path = mkstemp()
    new_file = open(abs_path,'w')
    old_file = open(file)
    for line in old_file:
        new_file.write(line.replace(pattern, subst))
    #close temp file
    new_file.close()
    close(fh)
    old_file.close()
    #Remove original file
    remove(file)
    #Move new file
    move(abs_path, file)


class MyScenario(run.Scenario):
    REPEATS = 10
    SETTINGS = core.Settings(max_steps=600, think_time=100)
    #SETTINGS = core.Settings(max_steps=600, think_time=0.01)
# The class name of each agentdistributeAmmo
agent1 = "AgentBase"
agent2 = "AgentSimple"

# Copy main file
mainFile = "domination/main.py"
mainFileCopy1 = "domination/mainDONOTEDIT1_" + agent1 + ".py"
mainFileCopy2 = "domination/mainDONOTEDIT2_" + agent2 + ".py"
shutil.copyfile(mainFile, mainFileCopy1)
shutil.copyfile(mainFile, mainFileCopy2)

# Open files and edit to use the right class
replace(mainFileCopy1, "__AUTOREPLACEME__", agent1);
replace(mainFileCopy2, "__AUTOREPLACEME__", agent2);

#MyScenario.test(red=mainFileCopy1, blue=mainFileCopy2)
#MyScenario.one_on_one(red=mainFileCopy1, blue=mainFileCopy2)


# 
config.load('xor2_config')

# set node gene type
chromosome.node_gene_type = genome.NodeGene

# XOR-2
INPUTS = [[0, 0], [0, 1], [1, 0], [1, 1]]
OUTPUTS = [0, 1, 1, 0]

def eval_fitness(population):
    for chromo in population:
        net = nn.create_ffphenotype(chromo)

        # Run a game and get results
        
        error = 0.0
        #error_stanley = 0.0
        for i, inputs in enumerate(INPUTS):
            net.flush() # not strictly necessary in feedforward nets
            output = net.sactivate(inputs) # serial activation
            error += (output[0] - OUTPUTS[i])**2

            #error_stanley += math.fabs(output[0] - OUTPUTS[i])

        #chromo.fitness = (4.0 - error_stanley)**2 # (Stanley p. 43)
        chromo.fitness = 1 - math.sqrt(error/len(OUTPUTS))

population.Population.evaluate = eval_fitness

pop = population.Population()
pop.epoch(300, report=True, save_best=False)

winner = pop.stats[0][-1]
print 'Number of evaluations: %d' %winner.id

# Visualize the winner network (requires PyDot)
#visualize.draw_net(winner) # best chromosome

# Plots the evolution of the best/average fitness (requires Biggles)
#visualize.plot_stats(pop.stats)
# Visualizes speciation
#visualize.plot_species(pop.species_log)

# Let's check if it's really solved the problem
#print '\nBest network output:'
#brain = nn.create_ffphenotype(winner)
#for i, inputs in enumerate(INPUTS):
#    output = brain.sactivate(inputs) # serial activation
#    print "%1.5f \t %1.5f" %(OUTPUTS[i], output[0])

# saves the winner
#file = open('winner_chromosome', 'w')
#pickle.dump(winner, file)
#file.close()
